package net.alche.fa.core.doing;

import java.util.Map;
import java.lang.Override;
import net.alche.fa.core.model.Logic;
import net.alche.fa.core.model.FaValue;
import net.alche.fa.core.CodeLevel;
import net.alche.fa.core.SageStone;
import net.alche.fa.core.FaException;

//
// if
//
@FaAnnoDoing
@SuppressWarnings("all") 
public class IfDo extends AbstractDoing {
  static Map<String,String> staticPath = null;
  static Map<String,Object> staticObjects = null;

  @Override
  public boolean matched(String what, Logic g) {
    return what != null && (what.startsWith("if") || what.equals("!") || what.equals("!=") || what.equals("==") || what.equals("<") || what.equals("<=") || what.equals(">") || what.equals(">=") || what.equals("else") || what.startsWith("else if") || what.startsWith("||") || what.startsWith("&&"));
  }

  @Override
  public FaValue doing(Logic g, CodeLevel lvl, SageStone st) throws FaException {
    String what = g.getWhat();
    if ( what.equals("else")) {
      if ( !lvl.ifStatus) {
        lvl.doChild = true;
      }
      else {
        lvl.doChild = false;
      }
      lvl.ifStatus = true;
      return new FaValue().aiData(true);
    }
    else if ( what.equals("else if") && lvl.ifStatus == true) {
      lvl.doChild = false;
      return new FaValue().aiData(false);
    }
    try {
      Logic compareLogic = g;
      if ( g.getLogicData() != null && "(".equals(g.getLogicData().getWhat()) && "if".equals(g.getWhat())) {
        compareLogic = g.getLogicObj();
      }
      else if ( "if".equals(g.getWhat()) && g.getLogicObj() != null) {
        compareLogic = g.getLogicObj();
      }
      if ( "&&".equals(compareLogic.getWhat()) || "||".equals(compareLogic.getWhat())) {
        what = compareLogic.getWhat();
      }
      FaValue varData = null;
      if ( ".".equals(compareLogic.getWhat()) || !what.equals("!") && "!".equals(compareLogic.getWhat())) {
        varData = super.getLogicValue(st, lvl, compareLogic );
      }
      else {
        varData = getLogicObjVal(st, lvl, compareLogic);
      }
      if ( what.equals("||")) {
        if ( varData.getBoolValue()) {
          lvl.ifStatus = true;
          return new FaValue().aiData(varData.getBoolValue());
        }
      }
      else if ( what.equals("&&")) {
        if ( !varData.getBoolValue()) {
          lvl.ifStatus = false;
          lvl.doChild = false;
          return new FaValue().aiData(varData.getBoolValue());
        }
      }
      String eq = compareLogic.getWhat();
      boolean isOk = false;
      if ( eq == null || ".".equals(eq)) {
        isOk = varData.getBoolValue();
      }
      else {
        FaValue data = getLogicDataVal(st, lvl, compareLogic);
        isOk = compare(varData, eq, data);
      }
      if ( what.equals("!")) {
        isOk = !isOk;
      }
      if ( !isOk) {
        lvl.ifStatus = false;
        lvl.doChild = false;
        return new FaValue().aiData(false);
      }
      else {
        lvl.ifStatus = true;
      }
    }
    catch ( Exception ex) {
      ex.printStackTrace();
      throw new FaException(ex);
    }
    return new FaValue().aiData(true);
  }

  public static boolean compare(FaValue ov, String runType, FaValue value) throws FaException {
    if ( value == null) {
      if ( ov.isNull()) {
        throw new FaException(FaException.NULL_ERROR, "" + ov.getVarName());
      }
      return ov.getBoolValue();
    }
    if ( ov == null) {
      if ( value.isNull()) {
        throw new FaException(FaException.NULL_ERROR, "" + value.getVarName());
      }
      return value.getBoolValue();
    }
    if ( ov.isNull() || value.isNull()) {
      return mathNull(ov, runType, value);
    }
    switch ( ov.getType()) {
      case FaValue._INT : {
        return mathInteger(ov.getIntValue(), runType, value.getIntValue());
      }
      case FaValue._BYTE : {
        return mathInteger(ov.getIntValue(), runType, value.getIntValue());
      }
      case FaValue._LONG : {
        return mathLong(ov.getLongValue(), runType, value.getLongValue());
      }
      case FaValue._BOOL : {
        return mathBoolean(ov.getBoolValue(), runType, value.getBoolValue());
      }
      case FaValue._DOUBLE : {
        return mathDouble(ov.getDoubleValue(), runType, value.getDoubleValue());
      }
      case FaValue._STRING : {
        return mathString(ov.getStrValue(), runType, value.getStrValue());
      }
    }
    return false;
  }

  static boolean mathNull(FaValue varData, String runType, FaValue value) {
    switch ( runType) {
      case "==" : {
        return varData.isNull() && value.isNull();
      }
      case "!=" : {
        if ( varData.getType() == FaValue._NULL) {
          return !value.isNull();
        }
        else {
          return !varData.isNull();
        }
      }
      default : {
        return false;
      }
    }
  }

  static boolean mathInteger(Integer varData, String runType, Integer value) {
    switch ( runType) {
      case "!=" : {
        return varData.intValue() != value.intValue();
      }
      case "==" : {
        return varData.intValue() == value.intValue();
      }
      case ">=" : {
        return varData.intValue() >= value.intValue();
      }
      case ">" : {
        return varData.intValue() > value.intValue();
      }
      case "<=" : {
        return varData.intValue() <= value.intValue();
      }
      case "<" : {
        return varData.intValue() < value.intValue();
      }
    }
    return false;
  }

  static boolean mathLong(Long varData, String runType, Long value) {
    switch ( runType) {
      case "!=" : {
        return varData.longValue() != value.longValue();
      }
      case "==" : {
        return varData.longValue() == value.longValue();
      }
      case ">=" : {
        return varData.longValue() >= value.longValue();
      }
      case ">" : {
        return varData.longValue() > value.longValue();
      }
      case "<=" : {
        return varData.longValue() <= value.longValue();
      }
      case "<" : {
        return varData.longValue() < value.longValue();
      }
    }
    return false;
  }

  static boolean mathDouble(Double varData, String runType, Double value) {
    switch ( runType) {
      case "!=" : {
        return varData.doubleValue() != value.doubleValue();
      }
      case "==" : {
        return varData.doubleValue() == value.doubleValue();
      }
      case ">=" : {
        return varData.doubleValue() >= value.doubleValue();
      }
      case ">" : {
        return varData.doubleValue() > value.doubleValue();
      }
      case "<=" : {
        return varData.doubleValue() <= value.doubleValue();
      }
      case "<" : {
        return varData.doubleValue() < value.doubleValue();
      }
    }
    return false;
  }

  static boolean mathString(String varData, String runType, String value) {
    switch ( runType) {
      case "==" : {
        return varData.equals(value);
      }
      case "!=" : {
        return !varData.equals(value);
      }
    }
    return false;
  }

  static boolean mathBoolean(Boolean varData, String runType, Boolean value) {
    switch ( runType) {
      case "==" : {
        return varData.booleanValue() == value.booleanValue();
      }
      case "!=" : {
        return varData.booleanValue() != value.booleanValue();
      }
      case "&&" : {
        return varData.booleanValue() && value.booleanValue();
      }
      case "if" : {
        return varData.booleanValue() && value.booleanValue();
      }
      case "||" : {
        return varData.booleanValue() || value.booleanValue();
      }
    }
    return false;
  }
}